home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / ole2book.zip / CHAP06.ZIP / CHAP06 / DATAUSER / DATAUSER.CPP next >
C/C++ Source or Header  |  1993-06-15  |  18KB  |  658 lines

  1. /*
  2.  * DATAUSER.CPP
  3.  *
  4.  * A user of the Data Objects for Chapter 6
  5.  *
  6.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  7.  *
  8.  * Kraig Brockschmidt, Software Design Engineer
  9.  * Microsoft Systems Developer Relations
  10.  *
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14.  
  15.  
  16. #define INITGUIDS
  17. #include "datauser.h"
  18.  
  19.  
  20. //These are for displaying clipboard formats textually.
  21. static char * rgszCF[13]={"Unknown", "CF_TEXT", "CF_BITMAP", "CF_METAFILEPICT"
  22.                  , "CF_SYLK", "CF_DIF", "CF_TIFF", "CF_OEMTEXT", "CF_DIB"
  23.                  , "CF_PALETTE", "CF_PENDATA", "CF_RIFF", "CF_WAVE"};
  24.  
  25.  
  26. static char szSuccess[]    ="succeeded";
  27. static char szFailed[]     ="failed";
  28. static char szExpected[]   ="expected";
  29. static char szUnexpected[] ="unexpected!";
  30.  
  31.  
  32. /*
  33.  * WinMain
  34.  *
  35.  * Purpose:
  36.  *  Main entry point of application.
  37.  */
  38.  
  39. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hInstPrev
  40.     , LPSTR pszCmdLine, int nCmdShow)
  41.     {
  42.     MSG         msg;
  43.     LPAPPVARS   pAV;
  44.  
  45.    #ifndef WIN32
  46.     SetMessageQueue(96);
  47.    #endif
  48.  
  49.     //Create and initialize the application.
  50.     pAV=new CAppVars(hInst, hInstPrev, nCmdShow);
  51.  
  52.     if (NULL==pAV)
  53.         return -1;
  54.  
  55.     if (pAV->FInit())
  56.         {
  57.         while (GetMessage(&msg, NULL, 0,0 ))
  58.             {
  59.             TranslateMessage(&msg);
  60.             DispatchMessage(&msg);
  61.             }
  62.         }
  63.  
  64.     delete pAV;
  65.     return msg.wParam;
  66.     }
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74. /*
  75.  * DataUserWndProc
  76.  *
  77.  * Purpose:
  78.  *  Window class procedure.  Standard callback.
  79.  */
  80.  
  81. LRESULT FAR PASCAL __export DataUserWndProc(HWND hWnd, UINT iMsg
  82.     , WPARAM wParam, LPARAM lParam)
  83.     {
  84.     HRESULT         hr;
  85.     LPAPPVARS       pAV;
  86.     HMENU           hMenu;
  87.     FORMATETC       fe;
  88.     WORD            wID;
  89.  
  90.     //This will be valid for all messages except WM_NCCREATE
  91.     pAV=(LPAPPVARS)GetWindowLong(hWnd, DATAUSERWL_STRUCTURE);
  92.  
  93.     switch (iMsg)
  94.         {
  95.         case WM_NCCREATE:
  96.             //CreateWindow passed pAV to us.
  97.             pAV=(LPAPPVARS)((LONG)((LPCREATESTRUCT)lParam)->lpCreateParams);
  98.  
  99.             SetWindowLong(hWnd, DATAUSERWL_STRUCTURE, (LONG)pAV);
  100.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  101.  
  102.         case WM_DESTROY:
  103.             PostQuitMessage(0);
  104.             break;
  105.  
  106.         case WM_PAINT:
  107.             pAV->Paint();
  108.             break;
  109.  
  110.         case WM_COMMAND:
  111.             SETDefFormatEtc(fe, 0, TYMED_HGLOBAL | TYMED_GDI | TYMED_MFPICT);
  112.  
  113.             hMenu=GetMenu(hWnd);
  114.             wID=LOWORD(wParam);
  115.  
  116.             switch (wID)
  117.                 {
  118.                 case IDM_OBJECTUSEDLL:
  119.                     if (!pAV->m_fEXE)
  120.                         break;
  121.  
  122.                     pAV->m_fEXE=FALSE;
  123.                     pAV->FReloadDataObjects(TRUE);
  124.                     break;
  125.  
  126.  
  127.                 case IDM_OBJECTUSEEXE:
  128.                     if (pAV->m_fEXE)
  129.                         break;
  130.  
  131.                     pAV->m_fEXE=TRUE;
  132.                     pAV->FReloadDataObjects(TRUE);
  133.                     break;
  134.  
  135.                 case IDM_OBJECTDATASIZESMALL:
  136.                 case IDM_OBJECTDATASIZEMEDIUM:
  137.                 case IDM_OBJECTDATASIZELARGE:
  138.                     CheckMenuItem(hMenu, IDM_OBJECTDATASIZESMALL,  MF_UNCHECKED);
  139.                     CheckMenuItem(hMenu, IDM_OBJECTDATASIZEMEDIUM, MF_UNCHECKED);
  140.                     CheckMenuItem(hMenu, IDM_OBJECTDATASIZELARGE,  MF_UNCHECKED);
  141.                     CheckMenuItem(hMenu, wID,  MF_CHECKED);
  142.  
  143.                     //Kill old advise.
  144.                     if (NULL!=pAV->m_pIDataObject || 0!=pAV->m_dwConn)
  145.                         pAV->m_pIDataObject->DUnadvise(pAV->m_dwConn);
  146.  
  147.                     if (IDM_OBJECTDATASIZELARGE==wID)
  148.                         pAV->m_pIDataObject=pAV->m_pIDataLarge;
  149.                     else if (IDM_OBJECTDATASIZEMEDIUM==wID)
  150.                         pAV->m_pIDataObject=pAV->m_pIDataMedium;
  151.                     else
  152.                         pAV->m_pIDataObject=pAV->m_pIDataSmall;
  153.  
  154.                     //Setup new advise.
  155.                     fe.cfFormat=pAV->m_cfAdvise;
  156.                     pAV->m_pIDataObject->DAdvise(&fe, ADVF_NODATA
  157.                         , pAV->m_pIAdviseSink, &pAV->m_dwConn);
  158.  
  159.                     break;
  160.  
  161.                 case IDM_OBJECTQUERYGETDATA:
  162.                     if (NULL==pAV->m_pIDataObject)
  163.                         break;
  164.  
  165.                     fe.tymed=TYMED_HGLOBAL | TYMED_GDI | TYMED_MFPICT;
  166.  
  167.                     pAV->TryQueryGetData(&fe, CF_TEXT,         TRUE,  0);
  168.                     pAV->TryQueryGetData(&fe, CF_BITMAP,       TRUE,  1);
  169.                     pAV->TryQueryGetData(&fe, CF_DIB,          FALSE, 2);
  170.                     pAV->TryQueryGetData(&fe, CF_METAFILEPICT, TRUE,  3);
  171.                     pAV->TryQueryGetData(&fe, CF_WAVE,         FALSE, 4);
  172.                     break;
  173.  
  174.  
  175.                 case IDM_OBJECTGETDATATEXT:
  176.                 case IDM_OBJECTGETDATABITMAP:
  177.                 case IDM_OBJECTGETDATAMETAFILEPICT:
  178.                     if (NULL==pAV->m_pIDataObject)
  179.                         break;
  180.  
  181.                     //Clean up whatever we currently have.
  182.                     pAV->m_cf=0;
  183.                     ReleaseStgMedium(&pAV->m_stm);
  184.  
  185.                     if (IDM_OBJECTGETDATATEXT==wID)
  186.                         SETDefFormatEtc(fe, CF_TEXT, TYMED_HGLOBAL);
  187.  
  188.                     if (IDM_OBJECTGETDATABITMAP==wID)
  189.                         SETDefFormatEtc(fe, CF_BITMAP, TYMED_GDI);
  190.  
  191.                     if (IDM_OBJECTGETDATAMETAFILEPICT==wID)
  192.                         SETDefFormatEtc(fe, CF_METAFILEPICT, TYMED_MFPICT);
  193.  
  194.                     pAV->m_stm.tymed=fe.tymed;
  195.                     hr=pAV->m_pIDataObject->GetData(&fe, &(pAV->m_stm));
  196.  
  197.                     if (SUCCEEDED(hr))
  198.                         pAV->m_cf=fe.cfFormat;
  199.  
  200.                     InvalidateRect(hWnd, NULL, TRUE);
  201.                     UpdateWindow(hWnd);
  202.                     break;
  203.  
  204.                 case IDM_OBJECTEXIT:
  205.                     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  206.                     break;
  207.  
  208.  
  209.                 case IDM_ADVISETEXT:
  210.                 case IDM_ADVISEBITMAP:
  211.                 case IDM_ADVISEMETAFILEPICT:
  212.                     if (NULL==pAV->m_pIDataObject)
  213.                         break;
  214.  
  215.                     //Terminate the old connection
  216.                     if (0!=pAV->m_dwConn)
  217.                         pAV->m_pIDataObject->DUnadvise(pAV->m_dwConn);
  218.  
  219.                     CheckMenuItem(hMenu, pAV->m_cfAdvise+IDM_ADVISEMIN, MF_UNCHECKED);
  220.                     CheckMenuItem(hMenu, wID, MF_CHECKED);
  221.  
  222.                     //New format is wID-IDM_ADVISEMIN
  223.                     pAV->m_cfAdvise=(UINT)(wID-IDM_ADVISEMIN);
  224.                     fe.cfFormat=pAV->m_cfAdvise;
  225.                     pAV->m_pIDataObject->DAdvise(&fe, ADVF_NODATA
  226.                         , pAV->m_pIAdviseSink, &pAV->m_dwConn);
  227.  
  228.                     break;
  229.  
  230.                 case IDM_ADVISEGETDATA:
  231.                     pAV->m_fGetData=!pAV->m_fGetData;
  232.                     CheckMenuItem(hMenu, wID, pAV->m_fGetData ? MF_CHECKED : MF_UNCHECKED);
  233.                     break;
  234.  
  235.                 case IDM_ADVISEREPAINT:
  236.                     pAV->m_fRepaint=!pAV->m_fRepaint;
  237.                     CheckMenuItem(hMenu, wID, pAV->m_fRepaint ? MF_CHECKED : MF_UNCHECKED);
  238.                     break;
  239.  
  240.                 default:
  241.                     break;
  242.                 }
  243.             break;
  244.  
  245.         default:
  246.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  247.         }
  248.  
  249.     return 0L;
  250.     }
  251.  
  252.  
  253.  
  254.  
  255.  
  256. /*
  257.  * CAppVars::CAppVars
  258.  * CAppVars::~CAppVars
  259.  *
  260.  * Constructor Parameters: (from WinMain)
  261.  *  hInst           HINSTANCE of the application.
  262.  *  hInstPrev       HINSTANCE of a previous instance.
  263.  *  nCmdShow        UINT specifying how to show the app window.
  264.  *
  265.  */
  266.  
  267. CAppVars::CAppVars(HINSTANCE hInst, HINSTANCE hInstPrev, UINT nCmdShow)
  268.     {
  269.     m_hInst       =hInst;
  270.     m_hInstPrev   =hInstPrev;
  271.     m_nCmdShow    =nCmdShow;
  272.  
  273.     m_hWnd        =NULL;
  274.     m_fEXE        =FALSE;
  275.  
  276.     m_pIAdviseSink =NULL;
  277.     m_dwConn       =0;
  278.     m_cfAdvise     =0;
  279.     m_fGetData     =FALSE;
  280.     m_fRepaint     =FALSE;
  281.  
  282.     m_pIDataSmall =NULL;
  283.     m_pIDataMedium=NULL;
  284.     m_pIDataLarge =NULL;
  285.     m_pIDataObject=NULL;
  286.  
  287.     m_cf=0;
  288.     m_stm.tymed=TYMED_NULL;
  289.     m_stm.lpszFileName=NULL;      //Initializes union contents to NULL.
  290.     m_stm.pUnkForRelease=NULL;
  291.  
  292.     m_fInitialized=FALSE;
  293.     return;
  294.     }
  295.  
  296.  
  297. CAppVars::~CAppVars(void)
  298.     {
  299.     //This releases the data object interfaces and advises
  300.     FReloadDataObjects(FALSE);
  301.  
  302.     ReleaseStgMedium(&m_stm);
  303.  
  304.     if (NULL!=m_pIAdviseSink)
  305.         m_pIAdviseSink->Release();
  306.  
  307.     if (IsWindow(m_hWnd))
  308.         DestroyWindow(m_hWnd);
  309.  
  310.     if (m_fInitialized)
  311.         CoUninitialize();
  312.  
  313.     return;
  314.     }
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322. /*
  323.  * CAppVars::FInit
  324.  *
  325.  * Purpose:
  326.  *  Initializes an CAppVars object by registering window classes,
  327.  *  creating the main window, and doing anything else prone to failure
  328.  *  such as calling CoInitialize.  If this function fails the caller
  329.  *  should insure that the destructor is called.
  330.  *
  331.  * Parameters:
  332.  *  None
  333.  *
  334.  * Return Value:
  335.  *  BOOL            TRUE if successful, FALSE otherwise.
  336.  */
  337.  
  338. BOOL CAppVars::FInit(void)
  339.     {
  340.     WNDCLASS    wc;
  341.     DWORD       dwVer;
  342.     BOOL        fRet;
  343.  
  344.     dwVer=CoBuildVersion();
  345.  
  346.     if (rmm!=HIWORD(dwVer))
  347.         return FALSE;
  348.  
  349.     if (FAILED(CoInitialize(NULL)))
  350.         return FALSE;
  351.  
  352.     m_fInitialized=TRUE;
  353.  
  354.     //Register our window classes.
  355.     if (!m_hInstPrev)
  356.         {
  357.         wc.style          = CS_HREDRAW | CS_VREDRAW;
  358.         wc.lpfnWndProc    = DataUserWndProc;
  359.         wc.cbClsExtra     = 0;
  360.         wc.cbWndExtra     = CBWNDEXTRA;
  361.         wc.hInstance      = m_hInst;
  362.         wc.hIcon          = LoadIcon(m_hInst, "Icon");
  363.         wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  364.         wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  365.         wc.lpszMenuName   = MAKEINTRESOURCE(IDR_MENU);
  366.         wc.lpszClassName  = "DATAUSER";
  367.  
  368.         if (!RegisterClass(&wc))
  369.             return FALSE;
  370.         }
  371.  
  372.     //Create the main window.
  373.     m_hWnd=CreateWindow("DATAUSER", "Data Object User"
  374.         , WS_OVERLAPPEDWINDOW,35, 35, 350, 250, NULL, NULL, m_hInst, this);
  375.  
  376.     if (NULL==m_hWnd)
  377.         return FALSE;
  378.  
  379.     ShowWindow(m_hWnd, m_nCmdShow);
  380.     UpdateWindow(m_hWnd);
  381.  
  382.     m_pIAdviseSink=new CImpIAdviseSink(this);
  383.  
  384.     if (NULL==m_pIAdviseSink)
  385.         return FALSE;
  386.  
  387.     m_pIAdviseSink->AddRef();
  388.  
  389.     CheckMenuItem(GetMenu(m_hWnd), IDM_OBJECTUSEDLL,         MF_CHECKED);
  390.     CheckMenuItem(GetMenu(m_hWnd), IDM_OBJECTDATASIZESMALL,  MF_CHECKED);
  391.  
  392.     //Load the initial objects
  393.     fRet=FReloadDataObjects(TRUE);
  394.     m_pIDataObject=m_pIDataSmall;
  395.  
  396.     return fRet;
  397.     }
  398.  
  399.  
  400.  
  401.  
  402.  
  403. /*
  404.  * CAppVars::FReloadDataObjects
  405.  *
  406.  * Purpose:
  407.  *  Releases the old data objects we're holding on to and reloads
  408.  *  the new ones from either EXE or DLL depending on m_fEXE.
  409.  *
  410.  * Parameters:
  411.  *  fReload         BOOL indicating if we are to recreate everything
  412.  *                  or just release the old ones (so we can use this
  413.  *                  from the destructor).
  414.  *
  415.  * Return Value:
  416.  *  BOOL            TRUE if there are usable objects in us now.
  417.  */
  418.  
  419. BOOL CAppVars::FReloadDataObjects(BOOL fReload)
  420.     {
  421.     HRESULT     hr1, hr2, hr3;
  422.     DWORD       dwClsCtx;
  423.     HCURSOR     hCur, hCurT;
  424.     HMENU       hMenu;
  425.     UINT        uTempD, uTempE;
  426.  
  427.     //Clean out any data we're holding
  428.     m_cf=0;
  429.     ReleaseStgMedium(&m_stm);
  430.  
  431.     //Turn off whatever data connection we have
  432.     if (NULL!=m_pIDataObject && 0!=m_dwConn)
  433.         m_pIDataObject->DUnadvise(m_dwConn);
  434.  
  435.     if (NULL!=m_pIDataLarge)
  436.         m_pIDataLarge->Release();
  437.  
  438.     if (NULL!=m_pIDataMedium)
  439.         m_pIDataMedium->Release();
  440.  
  441.     if (NULL!=m_pIDataSmall)
  442.         m_pIDataSmall->Release();
  443.  
  444.     m_pIDataObject=NULL;
  445.     CoFreeUnusedLibraries();
  446.  
  447.     //Exit if we just wanted to free.
  448.     if (!fReload)
  449.         return FALSE;
  450.  
  451.  
  452.     hCur=LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
  453.     hCurT=SetCursor(hCur);
  454.     ShowCursor(TRUE);
  455.  
  456.     dwClsCtx=(m_fEXE) ? CLSCTX_LOCAL_SERVER : CLSCTX_INPROC_SERVER;
  457.  
  458.     hr1=CoCreateInstance(CLSID_DataObjectSmall, NULL, dwClsCtx
  459.         , IID_IDataObject, (LPVOID FAR *)&m_pIDataSmall);
  460.  
  461.     hr2=CoCreateInstance(CLSID_DataObjectMedium, NULL, dwClsCtx
  462.         , IID_IDataObject, (LPVOID FAR *)&m_pIDataMedium);
  463.  
  464.     hr3=CoCreateInstance(CLSID_DataObjectLarge, NULL, dwClsCtx
  465.         , IID_IDataObject, (LPVOID FAR *)&m_pIDataLarge);
  466.  
  467.     ShowCursor(FALSE);
  468.     SetCursor(hCurT);
  469.  
  470.     //If anything fails, recurse to clean up...
  471.     if (FAILED(hr1) || FAILED(hr2) || FAILED(hr3))
  472.         return FReloadDataObjects(FALSE);
  473.  
  474.     //Reset the state of the menus for Small, no advise, no options.
  475.     hMenu=GetMenu(m_hWnd);
  476.     CheckMenuItem(hMenu, IDM_OBJECTDATASIZESMALL,  MF_CHECKED);
  477.     CheckMenuItem(hMenu, IDM_OBJECTDATASIZEMEDIUM, MF_UNCHECKED);
  478.     CheckMenuItem(hMenu, IDM_OBJECTDATASIZELARGE,  MF_UNCHECKED);
  479.  
  480.     m_pIDataObject=m_pIDataSmall;
  481.     CheckMenuItem(hMenu, m_cfAdvise+IDM_ADVISEMIN, MF_UNCHECKED);
  482.  
  483.     uTempE=m_fEXE  ? MF_CHECKED : MF_UNCHECKED;
  484.     uTempD=!m_fEXE ? MF_CHECKED : MF_UNCHECKED;
  485.  
  486.     CheckMenuItem(hMenu, IDM_OBJECTUSEDLL, uTempD);
  487.     CheckMenuItem(hMenu, IDM_OBJECTUSEEXE, uTempE);
  488.  
  489.     CheckMenuItem(hMenu, IDM_ADVISEGETDATA, MF_UNCHECKED);
  490.     CheckMenuItem(hMenu, IDM_ADVISEREPAINT, MF_UNCHECKED);
  491.  
  492.     m_fGetData=FALSE;
  493.     m_fRepaint=FALSE;
  494.  
  495.     //Cannot request data using async advises, so disable these.
  496.     uTempE=m_fEXE  ? MF_DISABLED | MF_GRAYED : MF_ENABLED;
  497.     EnableMenuItem(hMenu,  IDM_ADVISEGETDATA, uTempE);
  498.     EnableMenuItem(hMenu, IDM_ADVISEREPAINT, uTempE);
  499.  
  500.     return TRUE;
  501.     }
  502.  
  503.  
  504.  
  505. /*
  506.  * CAppVars::TryQueryGetData
  507.  *
  508.  * Purpose:
  509.  *  Centralized function call and output code for displaying results
  510.  *  of various IDataObject::QueryGetData calls.
  511.  *
  512.  * Parameters:
  513.  *  pFE             LPFORMATETC to test.
  514.  *  cf              UINT specific clipboard format to stuff in pFE before
  515.  *                  calling.  If zero, use whatever is already in pFE.
  516.  *  fExpect         BOOL indicating expected results (TRUE for success)
  517.  *  y               UINT line on which to print results.
  518.  *
  519.  * Return Value:
  520.  *  None
  521.  */
  522.  
  523. void CAppVars::TryQueryGetData(LPFORMATETC pFE, UINT cf, BOOL fExpect, UINT y)
  524.     {
  525.     char        szTemp[80];
  526.     LPSTR       psz1;
  527.     LPSTR       psz2;
  528.     UINT        cch;
  529.     HRESULT     hr;
  530.     HDC         hDC;
  531.  
  532.     if (0!=cf)
  533.         pFE->cfFormat=cf;
  534.  
  535.     hr=m_pIDataObject->QueryGetData(pFE);
  536.     psz1=(NOERROR==hr) ? szSuccess : szFailed;
  537.     psz2=((NOERROR==hr)==fExpect) ? szExpected : szUnexpected;
  538.  
  539.     hDC=GetDC(m_hWnd);
  540.     SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  541.     SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  542.  
  543.     if (CF_WAVE < cf || 0==cf)
  544.         cch=wsprintf(szTemp, "QueryGetData on %d %s (%s).", cf, psz1, psz2);
  545.     else
  546.         {
  547.         cch=wsprintf(szTemp, "QueryGetData on %s %s (%s)."
  548.             , (LPSTR)rgszCF[cf], psz1, psz2);
  549.         }
  550.  
  551.     //Don't overwrite other painted display.
  552.     SetBkMode(hDC, TRANSPARENT);
  553.     TextOut(hDC, 0, 16*y, szTemp, cch);
  554.  
  555.     ReleaseDC(m_hWnd, hDC);
  556.  
  557.     return;
  558.     }
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565. /*
  566.  * CAppVars::Paint
  567.  *
  568.  * Purpose:
  569.  *  Handles WM_PAINT for the main window by drawing whatever data we
  570.  *  have sitting in the STGMEDIUM at this time.
  571.  *
  572.  * Parameters:
  573.  *  None
  574.  *
  575.  * Return Value:
  576.  *  None
  577.  */
  578.  
  579. void CAppVars::Paint(void)
  580.     {
  581.     PAINTSTRUCT     ps;
  582.     HDC             hDC;
  583.     HDC             hMemDC;
  584.     LPMETAFILEPICT  pMF;
  585.     LPSTR           psz;
  586.     RECT            rc;
  587.     FORMATETC       fe;
  588.  
  589.     GetClientRect(m_hWnd, &rc);
  590.  
  591.     hDC=BeginPaint(m_hWnd, &ps);
  592.  
  593.     //May need to retrieve the data with EXE objects
  594.     if (m_fEXE)
  595.         {
  596.         if (TYMED_NULL==m_stm.tymed && 0!=m_cf)
  597.             {
  598.             SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI);
  599.  
  600.             if (NULL!=m_pIDataObject)
  601.                 m_pIDataObject->GetData(&fe, &m_stm);
  602.             }
  603.         }
  604.  
  605.     switch (m_cf)
  606.         {
  607.         case CF_TEXT:
  608.             psz=(LPSTR)GlobalLock(m_stm.hGlobal);
  609.  
  610.             if (NULL==psz)
  611.                 break;
  612.  
  613.             SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  614.             SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  615.  
  616.             DrawText(hDC, psz, lstrlen(psz), &rc, DT_LEFT | DT_WORDBREAK);
  617.             GlobalUnlock(m_stm.hGlobal);
  618.             break;
  619.  
  620.  
  621.         case CF_BITMAP:
  622.             hMemDC=CreateCompatibleDC(hDC);
  623.  
  624.             if (NULL!=SelectObject(hMemDC, (HGDIOBJ)m_stm.hGlobal))
  625.                 {
  626.                 BitBlt(hDC, 0, 0, rc.right-rc.left, rc.bottom-rc.top
  627.                     , hMemDC, 0, 0, SRCCOPY);
  628.                 }
  629.  
  630.             DeleteDC(hMemDC);
  631.             break;
  632.  
  633.  
  634.         case CF_METAFILEPICT:
  635.             pMF=(LPMETAFILEPICT)GlobalLock(m_stm.hGlobal);
  636.  
  637.             if (NULL==pMF)
  638.                 break;
  639.  
  640.             SetMapMode(hDC, pMF->mm);
  641.             SetWindowOrgEx(hDC, 0, 0, NULL);
  642.             SetWindowExtEx(hDC, pMF->xExt, pMF->yExt, NULL);
  643.  
  644.             SetViewportExtEx(hDC, rc.right-rc.left, rc.bottom-rc.top, NULL);
  645.  
  646.             PlayMetaFile(hDC, pMF->hMF);
  647.             GlobalUnlock(m_stm.hGlobal);
  648.             break;
  649.  
  650.  
  651.         default:
  652.             break;
  653.         }
  654.  
  655.     EndPaint(m_hWnd, &ps);
  656.     return;
  657.     }
  658.